package com.cloudfun.campusshare.service.impl;

import cn.hutool.core.util.StrUtil;
import com.cloudfun.campusshare.common.constant.KjtAuditStatus;
import cn.hutool.json.JSONUtil;
import com.cloudfun.campusshare.common.constant.ApplicationResult;
import com.cloudfun.campusshare.common.constant.StoreType;
import com.cloudfun.campusshare.common.constant.MerchantType;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.cloudfun.campusshare.common.constant.*;
import com.cloudfun.campusshare.common.exception.BusinessException;
import com.cloudfun.campusshare.common.model.dto.MerchantDto;
import com.cloudfun.campusshare.common.model.dto.ReplenishDTO;
import com.cloudfun.campusshare.common.model.dto.ReplenishStatusCountDTO;
import com.cloudfun.campusshare.common.model.vo.*;
import com.cloudfun.campusshare.common.response.BaseResult;
import com.cloudfun.campusshare.common.response.BaseResultFactory;
import com.cloudfun.campusshare.common.response.PageResult;
import com.cloudfun.campusshare.common.security.AuthenticationHolder;
import com.cloudfun.campusshare.entity.*;
import com.cloudfun.campusshare.repo.AuthOrgEntityRepo;
import com.cloudfun.campusshare.repo.AuthPersonEntityRepo;
import com.cloudfun.campusshare.repo.KjtSubMerchantRepo;
import com.cloudfun.campusshare.repo.UserEntityRepo;
import com.cloudfun.campusshare.repo.sql.SqlAuthOrg;
import com.cloudfun.campusshare.service.ApplicationService;
import com.cloudfun.campusshare.service.AttachmentService;
import com.cloudfun.campusshare.service.AuthService;
import com.cloudfun.campusshare.service.UserRelService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.persistence.EntityManager;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private UserEntityRepo userEntityRepo;

    @Autowired
    private AuthPersonEntityRepo authPersonEntityRepo;

    @Autowired
    private AuthOrgEntityRepo authOrgEntityRepo;

    @Autowired
    private AttachmentService attachmentService;

    @Autowired
    private ApplicationService applicationService;

    @Autowired
    private UserRelService userRelService;

    @Autowired
    private KjtSubMerchantRepo kjtSubMerchantRepo;

    @Override
    public BaseResult authPerson(AuthPersonVO authPersonVO) {
        // 用户表认证类型
        Optional<UserEntity> userEntityOptional = userEntityRepo.findById(AuthenticationHolder.getUserId());
        if (!userEntityOptional.isPresent()) {
            return BaseResultFactory.produceEmptyResult(Code.INVALID_USER);
        }
        UserEntity userEntity = userEntityOptional.get();
        userEntity.setAuthStatus(AuthStatus.AUTHING.getCode());
        userEntity.setAuthType(AuthType.PERSON.getCode());
        userEntityRepo.save(userEntity);
        // 认证表
        AuthPersonEntity authPersonEntity = authPersonEntityRepo.findbyUserId(userEntity.getId());
        if (ObjectUtils.isEmpty(authPersonEntity)) {
            authPersonEntity = new AuthPersonEntity();
            authPersonEntity.setId(UUID.randomUUID().toString());
            authPersonEntity.setUserId(AuthenticationHolder.getUserId());
        }
        authPersonEntity.setIdNum(authPersonVO.getIdNum());
        authPersonEntity.setName(authPersonVO.getName());
        authPersonEntityRepo.save(authPersonEntity);
        // 附件处理
        attachmentService.relateAttachment(AuthenticationHolder.getUserId(), authPersonVO.getAttachIdList(), AttachType.ID_CARD_FRONT);
        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
    }

    @Override
    @Transactional
    public BaseResult<?> authOrg(AuthOrgVO authOrgVO) {
//        // 用户表认证类型
//        Optional<UserEntity> userEntityOptional = userEntityRepo.findById(AuthenticationHolder.getUserId());
//        if (!userEntityOptional.isPresent()) {
//            return BaseResultFactory.produceEmptyResult(Code.INVALID_USER);
//        }
//        UserEntity userEntity = userEntityOptional.get();
//        // 认证中或者认证成功都不允许再提交
//        if (AuthStatus.AUTHING.getCode() == userEntity.getAuthStatus()) {
//            return BaseResultFactory.produceEmptyResult(Code.USER_AUTH_APPLIED);
//        }
//        if (AuthStatus.AUTH_SUCCESS.getCode() == userEntity.getAuthStatus()) {
//            return BaseResultFactory.produceEmptyResult(Code.USER_AUTH_SUCCEED);
//        }
//        userEntity.setAuthStatus(AuthStatus.AUTHING.getCode());
//        userEntity.setAuthType(AuthType.ORG.getCode());
//        userEntityRepo.save(userEntity);
        // 企业认证表
        AuthOrgEntity authOrgEntity = authOrgEntityRepo.findByUserId(AuthenticationHolder.getUserId());
        if (null == authOrgEntity) {
            authOrgEntity = new AuthOrgEntity();
            BeanUtil.copyProperties(authOrgVO, authOrgEntity);
        } else if (authOrgEntity.getResult() == ApplicationResult.PASSED) {
            return BaseResultFactory.produceEmptyResult(Code.USER_AUTH_SUCCEED);
        } else if (authOrgEntity.getResult() == ApplicationResult.PENDING_REVIEW) {
            return BaseResultFactory.produceEmptyResult(Code.USER_AUTH_APPLIED);
        } else {
            BeanUtil.copyProperties(authOrgVO, authOrgEntity, CopyOptions.create().setIgnoreNullValue(true));
        }
        if (authOrgVO.getHoldingBankPhoto() != null) {
            authOrgEntity.setHoldingBankPhoto(JSONUtil.toJsonStr(authOrgVO.getHoldingBankPhoto()));
        }
        if (authOrgVO.getBankCardPhoto() != null) {
            authOrgEntity.setBankCardPhoto(JSONUtil.toJsonStr(authOrgVO.getBankCardPhoto()));
        }
        if (authOrgVO.getBankHoldingIdCardPhoto() != null) {
            authOrgEntity.setBankHoldingIdCardPhoto(JSONUtil.toJsonStr(authOrgVO.getBankHoldingIdCardPhoto()));
        }
        if (authOrgVO.getBankCardFrontPhoto() != null) {
            authOrgEntity.setBankCardFrontPhoto(JSONUtil.toJsonStr(authOrgVO.getBankCardFrontPhoto()));
        }
        if (authOrgVO.getBankCardBackPhoto() != null) {
            authOrgEntity.setBankCardBackPhoto(JSONUtil.toJsonStr(authOrgVO.getBankCardBackPhoto()));
        }
        if (authOrgVO.getLegalHoldingCardPhoto() != null) {
            authOrgEntity.setLegalHoldingCardPhoto(JSONUtil.toJsonStr(authOrgVO.getLegalHoldingCardPhoto()));
        }
        if (authOrgVO.getLegalPersonIdCardFrontPhoto() != null) {
            authOrgEntity.setLegalPersonIdCardFrontPhoto(JSONUtil.toJsonStr(authOrgVO.getLegalPersonIdCardFrontPhoto()));
        }
        if (authOrgVO.getLegalPersonIdCardBackPhoto() != null) {
            authOrgEntity.setLegalPersonIdCardBackPhoto(JSONUtil.toJsonStr(authOrgVO.getLegalPersonIdCardBackPhoto()));
        }
        if (authOrgVO.getBusinessLicensePhoto() != null) {
            authOrgEntity.setBusinessLicensePhoto(JSONUtil.toJsonStr(authOrgVO.getBusinessLicensePhoto()));
        }
        if (authOrgVO.getDoorPhoto() != null) {
            authOrgEntity.setDoorPhoto(JSONUtil.toJsonStr(authOrgVO.getDoorPhoto()));
        }
        if (authOrgVO.getStoreInteriorPhotos() != null) {
            authOrgEntity.setStoreInteriorPhotos(JSONUtil.toJsonStr(authOrgVO.getStoreInteriorPhotos()));
        }
        if (authOrgVO.getPhotoOfLeaseContractDocument() != null) {
            authOrgEntity.setPhotoOfLeaseContractDocument(JSONUtil.toJsonStr(authOrgVO.getPhotoOfLeaseContractDocument()));
        }
        if (authOrgVO.getOtherInformation() != null) {
            authOrgEntity.setOtherInformation(JSONUtil.toJsonStr(authOrgVO.getOtherInformation()));
        }
        authOrgEntity.setUserId(AuthenticationHolder.getUserId());
//        authOrgEntity.setResult(ApplicationResult.PENDING_REVIEW);
        authOrgEntityRepo.save(authOrgEntity);
        // 关联附件
//        attachmentService.relateAttachment(authOrgEntity.getId(), authOrgVO.getAttachIdList(), AttachType.LICENSE);
        // 发起申请
//        applicationService.create(ApplicationType.USER_ORG_AUTH, authOrgEntity.getId(), this.getApplicationContentParams(authOrgEntity));
        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
    }

    @Override
    @Transactional
    public void deleteAuthOrg(String userId) {
        if (StringUtils.isBlank(userId)) {
            return;
        }
        AuthOrgEntity authOrgEntity = authOrgEntityRepo.findByUserId(userId);
        if (null == authOrgEntity) {
            return;
        }
        // 删除申请
        applicationService.deleteByBizId(authOrgEntity.getId());
        // 删除附件
        attachmentService.deleteAttachment(authOrgEntity.getId(), AttachType.LICENSE);
        // 删除企业认证
        authOrgEntityRepo.delete(authOrgEntity);
    }

    private List<String> getApplicationContentParams(AuthOrgEntity authOrgEntity) {
        List<String> res = new ArrayList<>();
        res.add(authOrgEntity.getOrgName());
        res.add(authOrgEntity.getSocialCode());
        res.add(authOrgEntity.getName());
        res.add(authOrgEntity.getIdNum());
        res.add(authOrgEntity.getBankAccountName());
        res.add(authOrgEntity.getBankAccount());
        res.add(authOrgEntity.getDetailAddr());
        return res;
    }

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public BaseResult authInfo() {
        // 用户表认证类型
        AuthOrgEntity authOrgEntity = authOrgEntityRepo.findByUserId(AuthenticationHolder.getUserId());
        if (authOrgEntity == null) {
            AuthSimpleVO authSimpleVO = new AuthSimpleVO();
            authSimpleVO.setStatus(ApplicationResult.UNAUTH.getValue());
            return BaseResultFactory.produceResult(Code.SUCCESS, authSimpleVO);
        }
        // 认证成功或认证中
        return this.authInfo(authOrgEntity);
    }

    private BaseResult<AuthSimpleVO> authInfo(AuthOrgEntity authOrgEntity) {

        AuthSimpleVO authSimpleVO = new AuthSimpleVO();

        BeanUtil.copyProperties(authOrgEntity, authSimpleVO);
        authSimpleVO.setStatus(authOrgEntity.getResult().getValue());
        authSimpleVO.setSocialCode(authOrgEntity.getSocialCode());
        authSimpleVO.setDetailAddr(authOrgEntity.getDetailAddr());
        // 附件信息
        authSimpleVO.setAttachVOList(attachmentService.getAttachment(authOrgEntity.getId(), Arrays.asList(AttachType.LICENSE)));
        // 认证失败
        if (authOrgEntity.getResult() == ApplicationResult.FAILED) {
            // 备注
//            AuditEntity audit = applicationService.getLatestAuditByBizIdAndType(authOrgEntity.getId(), ApplicationType.USER_ORG_AUTH);
            authSimpleVO.setAuthResultDesc(authOrgEntity.getRemark());
            return BaseResultFactory.produceResult(Code.SUCCESS, authSimpleVO);
        }
        return BaseResultFactory.produceResult(Code.SUCCESS, authSimpleVO);
    }

    @Override
    public BaseResult<?> operationalAudit() {
        AuthOrgEntity authOrgEntity = authOrgEntityRepo.findByUserId(AuthenticationHolder.getUserId());
        if (authOrgEntity.getResult() != ApplicationResult.PASSED) {
            authOrgEntity.setResult(ApplicationResult.PENDING_REVIEW);
            authOrgEntityRepo.save(authOrgEntity);
        }
        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
    }

    @Override
    public BaseResult authAudit(MerchantAuditVo auditVo) {
        // 用户表认证类型
        AuthOrgEntity authOrgEntity = authOrgEntityRepo.findByUserId(auditVo.getUserId());
        authOrgEntity.setResult(auditVo.getResult());
        authOrgEntity.setRemark(auditVo.getRemark());
        authOrgEntityRepo.save(authOrgEntity);
        if (authOrgEntity.getResult() == ApplicationResult.PASSED) {
            UserEntity userEntity = userEntityRepo.findById(authOrgEntity.getUserId()).get();
            userEntity.setAuthStatus(authOrgEntity.getResult().getValue());
            userEntity.setEnterpriseName(authOrgEntity.getOrgName());
            userEntityRepo.save(userEntity);
        }
        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
    }

    @Override
    public BaseResult<?> updateOrgAuth(AuthOrgVO authOrgVO) {
        // 目前只支持地址的修改
        AuthOrgEntity authOrgEntity = authOrgEntityRepo.findTopByUserIdOrderByCreateTimeDesc(AuthenticationHolder.getUserId());
        if (ObjectUtils.isEmpty(authOrgEntity)) {
            return BaseResultFactory.produceEmptyResult(Code.NODATA);
        }
        authOrgEntity.setDetailAddr(authOrgVO.getDetailAddr());
        authOrgEntityRepo.save(authOrgEntity);
        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
    }

    @Override
    public BaseResult<AuthOrgEntity> get(String userId) {
        if (!AuthenticationHolder.isAdmin()) {
            userId = AuthenticationHolder.getUserId();
        }
        AuthOrgEntity authOrgEntity = authOrgEntityRepo.findByUserId(userId);
        UserEntity userEntity = userEntityRepo.findById(userId).get();
        Optional<SubMerchantEntity> kjtSubMerchantRepoByUserId = kjtSubMerchantRepo.findByUserId(userId);
        if (kjtSubMerchantRepoByUserId.isPresent()) {
            authOrgEntity.setKjtAuditStatus(kjtSubMerchantRepoByUserId.get().getAuditStatus());
        }
        authOrgEntity.setUserName(userEntity.getUsername());
        return BaseResultFactory.produceSuccess(authOrgEntity);
    }

    private void checkPageNum(int pageNum) {
        if (pageNum < 1) {
            log.error("分页查询异常，页码小于1");
            throw new BusinessException(Code.PARAMETER_ERROR);
        }
    }


    @Override
    public PageResult<MerchantVo> findAll(MerchantDto merchantDto) {
        checkPageNum(merchantDto.getPageNum());
        StringBuffer buffer = new StringBuffer(SqlAuthOrg.AUDIT_LIST);
        if (merchantDto.getAuditStatus() != null) {
            buffer.append(StrUtil.format(" AND auth_org.result='{}'", merchantDto.getAuditStatus()));
        }
        if (merchantDto.getKjtAuditStatus() == KjtAuditStatus.D) {
            buffer.append(" AND kjt_sub_merchant.audit_status is null");
        } else if (merchantDto.getKjtAuditStatus() != null) {
            buffer.append(StrUtil.format(" AND kjt_sub_merchant.audit_status='{}'", merchantDto.getKjtAuditStatus()));
        }
        if (merchantDto.getKeyWord() != null) {
            buffer.append(StrUtil.format(" AND auth_org.org_name='{}' OR user.username='{}'", merchantDto.getKeyWord(), merchantDto.getKeyWord()));
        }
        PageResult<MerchantVo> pageResult = authOrgEntityRepo.findNativeNamedQuery(buffer.toString(), PageRequest.of(merchantDto.getPageNum(), merchantDto.getPageSize()), MerchantVo.class);
        return pageResult;
    }

    @Override
    public ReviewOverviewVo reviewOverview() {
        ReviewOverviewVo reviewOverviewVo = new ReviewOverviewVo();
        reviewOverviewVo.setAuditPassedNum(authOrgEntityRepo.findCount(StrUtil.format("SELECT * FROM  auth_org WHERE result='{}'", ApplicationResult.PASSED)).intValue());
        reviewOverviewVo.setPendingReviewNum(authOrgEntityRepo.findCount(StrUtil.format("SELECT * FROM  auth_org WHERE result='{}'", ApplicationResult.PENDING_REVIEW)).intValue());
        reviewOverviewVo.setKjtUnsubmitted(authOrgEntityRepo.findCount(new StringBuffer(SqlAuthOrg.AUDIT_STATUS).append(" WHERE kjt_sub_merchant.audit_status is NULL").toString()).intValue());
        reviewOverviewVo.setKjtAuditFail(authOrgEntityRepo.findCount(new StringBuffer(SqlAuthOrg.AUDIT_STATUS).append(StrUtil.format(" WHERE kjt_sub_merchant.audit_status='{}'", KjtAuditStatus.F)).toString()).intValue());
        return reviewOverviewVo;
    }


}
